package com.wn.ziroom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wn.ziroom.entity.Room;
import com.wn.ziroom.esdao.RoomDao;
import com.wn.ziroom.mapper.RoomMapper;
import com.wn.ziroom.service.RoomService;
import com.wn.ziroom.vo.*;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author wangzhijia
 * @since 2023-02-23 02:27:54
 */
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements RoomService {

    @Autowired
    private RoomMapper roomMapper;

    @Autowired
    private RoomDao roomDao;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchTemplate;


    @Override
    public Page<Room> getRoomList(Integer num, Integer size,
                                  Condition condition) {

        Date date = null;
        Integer startRent = null;
        Integer endRent = null;

        String timeType = condition.getTime();
        String rentScope = condition.getRent();
        String[] streetCodeArr = condition.getStreetCode();

        String quartersName = condition.getQuarterName();
        String isOrderByArea = String.valueOf(condition.getIsOrderByArea());
        String isOrderByPrice = String.valueOf(condition.getIsOrderByPrice());


        //处理时间条件,把时间条件处理成Date对象然后匹配,结束时间大于这个时间的
        if (!StringUtils.isEmpty(timeType)) {
            date = new Date();
            if (timeType.equals("1")) {

                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.YEAR, 1); //增加一年
                date = cal.getTime();

            } else if (Integer.parseInt(timeType) > 1) {

                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.YEAR, Integer.parseInt(timeType));
                date = cal.getTime();

            } else if (timeType.equals("-1")) {

                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.MONTH, 3);
                date = cal.getTime();
            }
        }

        //处理金钱条件 前端传过来的是 2000-5000这样的字符串
        if (rentScope != null && !rentScope.equals("")) {
            startRent = Integer.parseInt(rentScope.split("-")[0]);
            endRent = Integer.parseInt(rentScope.split("-")[1]);
        }

        //处理地址条件


        Page<Room> roomPage = new Page<>(num, size);
        Page<Room> pageInfo = roomMapper.selectByConditionList(roomPage, streetCodeArr, startRent, endRent, date, isOrderByArea, isOrderByPrice, quartersName);


        return pageInfo;
    }

    @Override
    public RoomDetailVo getRoomDetail(Integer id) {
        return roomMapper.selectRoomDetailAndQuarter(id);
    }


    //基于es实现的房源查询
    @Override
    public Page<EsRoomVo> getRoomListEs(Integer num, Integer size, Condition condition) {
        String timeType = condition.getTime();
        String rentScope = condition.getRent();
        String[] streetCodeArr = condition.getStreetCode();

        String quartersName = condition.getQuarterName();
        String type = condition.getType();


        Integer isOrderByArea = condition.getIsOrderByArea();
        Integer isOrderByPrice = condition.getIsOrderByPrice();


        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();


        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();


        if (!StringUtils.isEmpty(quartersName)) {
            boolQueryBuilder.must(QueryBuilders.multiMatchQuery(quartersName, "name", "position"));
        }

        if (!StringUtils.isEmpty(type)) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("type", type));
        }

        //处理时间条件
        if (!StringUtils.isEmpty(timeType)) {
            Date date = new Date();
            if (timeType.equals("1")) {

                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.YEAR, 1); //增加一年
                date = cal.getTime();

            } else if (Integer.parseInt(timeType) > 1) {

                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.YEAR, Integer.parseInt(timeType));
                date = cal.getTime();

            } else if (timeType.equals("-1")) {

                Calendar cal = Calendar.getInstance();
                cal.setTime(date);
                cal.add(Calendar.MONTH, 3);
                date = cal.getTime();
            }
            boolQueryBuilder.must(QueryBuilders.rangeQuery("endTime").gt(date));
        }


        if (!StringUtils.isEmpty(rentScope)) {
            if (!rentScope.equals("")) {
                Integer startRent = Integer.parseInt(rentScope.split("-")[0]);
                Integer endRent = Integer.parseInt(rentScope.split("-")[1]);
                boolQueryBuilder.must(QueryBuilders.rangeQuery("rent").gte(startRent).lte(endRent));
            }
        }

        if (streetCodeArr != null && streetCodeArr.length > 0) {
            boolQueryBuilder.must(QueryBuilders.termsQuery("StreetCode", streetCodeArr));
        }

        nativeSearchQueryBuilder.withQuery(boolQueryBuilder).withPageable(PageRequest.of(num - 1, size));

        //组装面积排序条件
        if (isOrderByArea != null) {
            //2是升序
            //3是降序
            //1 不排序
            Sort areaSort = Sort.by("area");
            switch (isOrderByArea) {
                case 2:
                    nativeSearchQueryBuilder.withSort(Sort.by("area").ascending());
                    break;
                case 3:
                    nativeSearchQueryBuilder.withSort(Sort.by("area").descending());
                    break;
            }

        }

        NativeSearchQuery nativeSearchQuery = nativeSearchQueryBuilder.build();
        SearchHits<EsRoomVo> searchHits = elasticsearchTemplate.search(nativeSearchQuery, EsRoomVo.class);
        List<SearchHit<EsRoomVo>> searchHitList = searchHits.getSearchHits();

        List<EsRoomVo> roomVoList = searchHitList.stream().map(SearchHit::getContent).collect(Collectors.toList());


        //组装分页对象
        Page<EsRoomVo> pageInfo = new Page<>();

        long totalHits = searchHits.getTotalHits();
        pageInfo.setRecords(roomVoList);
        pageInfo.setCurrent(num);
        pageInfo.setSize(size);
        pageInfo.setTotal(totalHits);
        pageInfo.setPages((totalHits + size - 1) / size);


        return pageInfo;
    }

    @Override
    public Room add(Room room) {
        roomMapper.insert(room);
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("start_time",room.getStartTime());
        queryWrapper.eq("end_time",room.getEndTime());
        queryWrapper.eq("owner_id",room.getOwnerId());
        queryWrapper.eq("rent",room.getRent());
        return  roomMapper.selectOne(queryWrapper);
    }

    @Override
    public List<Room> selectById(Integer id) {
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("owner_id",id);
        return roomMapper.selectList(queryWrapper);
    }

    @Override
    public List<RoomVoo> selectRoomVooById(Integer id) {
        return  roomMapper.slectRoomVooByID(id);
    }

    @Override
    public List<RoomVvo> selectRoomVvoById(Integer id) {
        return  roomMapper.slectRoomVvoByID(id);

    }

    @Override
    public RoomUo selectUserById(Integer id) {
        return roomMapper.selectRoomUoById(id);
    }

    @Override
    public Room selectByUserId(Integer id) {
       return query().eq("user_id",id).one();
    }


}
